# Created by 黄景涛
# DATE 2024/5/27

""" 构造一颗实例拓扑树 """
import random
from datetime import datetime


class TreeNode:
    def __init__(self, value):
        self.value = value
        self.inst_id = None
        self.model_info = None
        self.children = []
        self.parents = []


class AsstTree:

    @classmethod
    def create_tree(cls, depth, max_children=4, idx=None):
        """
        实例的拓扑树
        :param depth: 深度
        :param max_children: max范围内，随机出子节点数量
        :param idx: 实例命名的序号
        :return: 根节点
        """
        if depth == 0:
            return None
        idx = '' if idx is None else '_' + str(idx + 1)
        value = f"实例{depth}" + idx
        root = TreeNode(value)
        for i in range(random.randint(1, max_children)):
            root.children.append(cls.create_tree(depth - 1, idx=i))
        return root

    @classmethod
    def update_node_by_dfs(cls, node: TreeNode, update_info, depth=0):
        """更新节点的model_info"""
        if node is None:
            return
        # 更新当前节点
        node.model_info = update_info[depth]
        for child in node.children:
            cls.update_node_by_dfs(child, update_info, depth + 1)  # 递归遍历子节点

    @classmethod
    def update_inst_by_dfs(cls, node: TreeNode, inst_func):
        """更新节点的value、inst_id"""
        if node is None:
            return

        # 创建实例,更新当前节点
        bk_obj_id = node.model_info[0]
        bk_inst_name = f"{str(bk_obj_id[-3:])}_实例" + str(datetime.now().strftime('%M%S')) + ''.join(
            random.choices('0123456789', k=2))
        bk_inst_id = inst_func(bk_inst_name, bk_obj_id)
        node.value = bk_inst_name
        node.inst_id = bk_inst_id
        for child in node.children:
            cls.update_inst_by_dfs(child, inst_func)

    @classmethod
    def update_asst_by_dfs(cls, node: TreeNode, asst_func):
        """创建父子节点之间的关联"""
        if node is None:
            return

        # 更新当前节点的关联关系
        bk_inst_name = node.value
        bk_inst_id = node.inst_id
        bk_obj_id = node.model_info[0]
        bk_obj_asst_ids = node.model_info[3:]
        for child in node.children:
            if child is not None:
                bk_asst_inst_name = child.value
                bk_asst_inst_id = child.inst_id
                bk_obj_id_2 = child.model_info[0]
                for asst_id in bk_obj_asst_ids:
                    if bk_obj_id_2 not in asst_id:
                        continue
                    asst_func(bk_inst_name, bk_asst_inst_name, bk_inst_id, bk_asst_inst_id, asst_id, bk_obj_id)
            cls.update_asst_by_dfs(child, asst_func)

    def print_tree(self, node, indent=0):
        """
        打印树结构
        TODO 可视化视图打印
        :param node: 根节点
        :param indent: 缩进
        :return: None
        """
        if node is None:
            return

        # output_msg = "    " * indent + node.value + f'\t{node.model_info}'
        output_msg = "    " * indent + node.value + f'\t{node.inst_id}'
        if node.children[-1] is not None:
            extract_info = f'{[n.value for n in node.children if hasattr(n, "value")]}'
            output_msg += f'{extract_info:->{100 - len(output_msg)}}'

        self.print_to_file(output_msg)
        for child in node.children:
            self.print_tree(child, indent + 1)

    @staticmethod
    def print_to_file(msg):
        file_name = f'../ass_tree_data.txt'
        with open(file_name, mode='a', encoding='utf8') as f:
            # print(msg, file=f)
            print(msg, file=None)


if __name__ == '__main__':
    tree = AsstTree()
    root = tree.create_tree(5)
    tree.update_node_by_dfs(root, [['a', True], ['b', False], ['c', True], ['d', False], ['e', True]])
    tree.print_tree(root)
